﻿using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using SqlSugarAndEntity;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Core;
using Core.JwtHelper;
using Core.HttpHelper;

namespace WebApi.Middleware
{
    // You may need to install the Microsoft.AspNetCore.Http.Abstractions package into your project
    public class LogMiddleware
    {
        private readonly RequestDelegate _next;
        private IBaseMethod baseMethod;

        public LogMiddleware(RequestDelegate next, IBaseMethod baseMethod)
        {
            _next = next;
            this.baseMethod = baseMethod;
        }

        public async Task Invoke(HttpContext httpContext)
        {
            //先判断这个请求是否需要记录日志
            var attr= HttpContextHelper.GetMetadata<NotLogAttribute>(httpContext);
            //不需要记录日志 直接走
            if (attr != null)
            {
                await _next(httpContext);
            }
            else
            {
                sys_loginfo loginfo = new sys_loginfo();
                Stopwatch stopwatch = new Stopwatch();
                //计时
                stopwatch.Start();
                //拦截请求,获得请求参数
                if (httpContext.Request.Headers.TryGetValue("Bear", out var apiKeyHeaderValues))
                {
                    var userinfo = JwtHelper.GetInfoByJwt(apiKeyHeaderValues.ToString());
                    loginfo.UserId = userinfo.Value<decimal>("ID");
                }
                loginfo.UserIP = httpContext.Connection.RemoteIpAddress?.ToString();
                loginfo.RequestMethod = httpContext.Request.Method.Trim().ToUpper();
                loginfo.RequestPath = httpContext.Request.Path;
                if (loginfo.RequestMethod == "GET" || loginfo.RequestMethod == "DELETE")
                {
                    loginfo.RequestParameter = httpContext.Request.QueryString.Value;
                }
                else
                {
                    var pamara = await HttpContextHelper.GetRequestBody(httpContext.Request.Body);
                    //擦除用户密码
                    if (pamara.ContainsKey("UserPassWord"))
                    {
                        pamara.Remove("UserPassWord");
                    }
                    loginfo.RequestParameter = pamara.ToString();
                }
                //执行正常逻辑
                var originalBodyStream = httpContext.Response.Body;
                using (var responseBody = new MemoryStream())
                {
                    httpContext.Response.Body = responseBody;
                    await _next(httpContext);
                    stopwatch.Stop();
                    loginfo.CreateTime = DateTime.Now;
                    loginfo.Duration = (int)stopwatch.ElapsedMilliseconds;
                    JObject obj = await HttpContextHelper.GetResponse(httpContext.Response);
                    await responseBody.CopyToAsync(originalBodyStream);
                    string res = JsonConvert.SerializeObject(obj);
                    loginfo.ResponseResult = res;
                    loginfo.ResponseCode = obj.Value<int>("code");
                }
                httpContext.Response.OnCompleted(() =>
                {
                    baseMethod.Db().Insertable(loginfo).ExecuteCommandAsync();
                    return Task.CompletedTask;
                });


            }
        }
    }

    // Extension method used to add the middleware to the HTTP request pipeline.
    public static class LogMiddlewareExtensions
    {
        public static IApplicationBuilder UseLogMiddleware(this IApplicationBuilder builder)
        {
            return builder.UseMiddleware<LogMiddleware>();
        }
    }
}
